package com.ldy.gkrpc.server;

import com.ldy.gkrpc.codec.Decoder;
import com.ldy.gkrpc.codec.Encoder;
import com.ldy.gkrpc.common.utils.ReflectionUtils;
import com.ldy.gkrpc.proto.Request;
import com.ldy.gkrpc.proto.Response;
import com.ldy.gkrpc.transport.RequestHandler;
import com.ldy.gkrpc.transport.TransportServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import java.io.IOException;

/**
 * @Description
 * @Author
 * @Date 2020/4/13 20:25
 **/
@Slf4j
public class RpcServer {
    private RpcServerConfig config;
    /**
     * 网络服务端
     */
    private TransportServer net;
    private Encoder encoder;
    private Decoder decoder;
    private ServiceManager serviceManager;
    private ServiceInvoker serviceInvoker;

    public RpcServer(RpcServerConfig config) {
        this.config = config;
        this.net = ReflectionUtils.newInstance(config.getTransportClass());
        this.net.init(config.getPort(), this.handler);
        this.encoder = ReflectionUtils.newInstance(config.getEncoderClass());
        this.decoder = ReflectionUtils.newInstance(config.getDecoderClass());
        this.serviceManager = new ServiceManager();
        this.serviceInvoker = new ServiceInvoker();

    }

    public <T> void register(Class<T> interfaceClass, T bean) {
        serviceManager.register(interfaceClass, bean);
    }

    public void start() {
        this.net.start();
    }

    public void stop() {
        this.net.stop();
    }

    private RequestHandler handler = (receive, toResp) -> {
        Response response = new Response();
        try {
            byte[] inBytes = IOUtils.readFully(receive, receive.available());
            Request request = decoder.decode(inBytes, Request.class);
            log.info("rpc get request {}",request);
            //找到对应的服务
            ServiceInstance serviceInstance = serviceManager.lookup(request);
            Object obj = serviceInvoker.invoker(serviceInstance, request);
            response.setData(obj);
        } catch (IOException e) {
           log.warn(e.getMessage(),e);
            response.setCode(1);
            response.setMessage(String.format("rpcServer got error:%s:%s",e.getClass().getName(),e.getMessage()));
        }finally {
            byte[] encode = encoder.encode(response);
            toResp.write(encode);
            log.info("response client");
        }
    };
}